
#include "../inc/HTMLParser.h"

		HTMLParser::HTMLParser(){}

		HTMLParser::~HTMLParser(){}

		string* HTMLParser::getDescription(const string *html){

			HTMLTokenizer tokenizer(*html);
			string *description=new string("");
			string h("h"),H("H");

			bool stopflag=false,scriptflag=false;

			//Makes up to 3 passes, first looking for title, then looking for header, then looking for body

			//get description from title
			while (tokenizer.HasNextToken()&&!stopflag) {
				HTMLToken current(tokenizer.GetNextToken());

				if (current.GetType()==TAG_START){
					string value=current.GetValue();

					if(strcasecmp(value.c_str(),"title")==0){

						while(!stopflag &&tokenizer.HasNextToken()){

							current=tokenizer.GetNextToken();
							if (current.GetType()==TAG_START && strcasecmp(current.GetValue().c_str(),"script")==0){
								scriptflag=true;
							}
							else if(current.GetType()==TAG_END){
								if(strcasecmp(current.GetValue().c_str(),"script")==0)
									scriptflag=false;
								else if(strcasecmp(current.GetValue().c_str(),"title")==0)
									stopflag=true;
							}
							else if (current.GetType()==TEXT && !scriptflag){
								*description += StringUtil::EncodeToXmlCopy(StringUtil::TrimCopy(current.GetValue()) + " ");

							}
						}

					}
				}
			}
			if (description->length()==0)
				stopflag=false;

			//get description from header
			tokenizer=HTMLTokenizer(*html);
			while (tokenizer.HasNextToken()&&!stopflag) {
				HTMLToken current(tokenizer.GetNextToken());
				if (current.GetType()==TAG_START){
					string value=current.GetValue();

					if((StringUtil::IsPrefix(value,h)||StringUtil::IsPrefix(value,H))&& isdigit(value[1])!=0){
						string starttag(value);
						while(!stopflag && tokenizer.HasNextToken()){
							current=tokenizer.GetNextToken();
							if (current.GetType()==TAG_START && strcasecmp(current.GetValue().c_str(),"script")==0){
								scriptflag=true;
							}
							else if(current.GetType()==TAG_END){
								if(strcasecmp(current.GetValue().c_str(),"script")==0)
									scriptflag=false;
								else if(strcasecmp(current.GetValue().c_str(),starttag.c_str())==0)
									stopflag=true;
							}
							else if (current.GetType()==TEXT && !scriptflag)
								*description += StringUtil::EncodeToXmlCopy(StringUtil::TrimCopy(current.GetValue()) + " ");
						}
					}
				}
			}
			if (description->length()==0)
				stopflag=false;

			//Get description from body
			tokenizer=HTMLTokenizer(*html);
			int length=0;
			while (tokenizer.HasNextToken()&&!stopflag) {
				HTMLToken current(tokenizer.GetNextToken());
				if (current.GetType()==TAG_START){
					string value=current.GetValue();

					if(strcasecmp(value.c_str(),"body")==0){
						string starttag(value);
						while(!stopflag&&tokenizer.HasNextToken()&&length<=100){
							current=tokenizer.GetNextToken();
							if (current.GetType()==TAG_START && strcasecmp(current.GetValue().c_str(),"script")==0){
								scriptflag=true;
							}
							else if(current.GetType()==TAG_END){
								if(strcasecmp(current.GetValue().c_str(),"script")==0)
									scriptflag=false;
								else if(strcasecmp(current.GetValue().c_str(),"body")==0)
									stopflag=true;
							}
							else if (current.GetType()==TEXT && !scriptflag){
								string temp(StringUtil::TrimCopy(current.GetValue()));
								length = ParseDescrtiptionText(temp, description, length);
							}
						}
					}
				}
			}
			*description = StringUtil::TrimCopy(*description);
			return description;
		}

		int HTMLParser::ParseDescrtiptionText(string &src, string *dest, int charCount){
			int pos=0;
			while (charCount<100 && pos < src.length()){
				if (!isspace(src[pos]))
					charCount++;
				pos++;
			}
			*dest= *dest+ StringUtil::EncodeToXmlCopy(src.substr(0,pos)) + " ";
			return charCount;
		}


		LinkedList<string>* HTMLParser::getWords(const string *html){
			HTMLTokenizer tokenizer(*html);
			LinkedList<string> *words = new LinkedList<string>();

			while(strcasecmp(tokenizer.GetNextToken().GetValue().c_str(),"html")!=0){
				if (!tokenizer.HasNextToken())
					throw new NonHTMLFileException();
			}

			bool titleflag=false,bodyflag=false,scriptflag=false;


			while(tokenizer.HasNextToken()){
				HTMLToken current(tokenizer.GetNextToken());
				if (current.GetType()== TAG_START){
					if(strcasecmp(current.GetValue().c_str(),"body")==0){
						bodyflag=true;
					}
					else if(strcasecmp(current.GetValue().c_str(),"title")==0){
						titleflag=true;
					}
					else if(strcasecmp(current.GetValue().c_str(),"script")==0){
						scriptflag=true;
					}
				}
				else if (current.GetType()== TAG_END){
					if(strcasecmp(current.GetValue().c_str(),"body")==0){
						bodyflag=false;
					}
					else if(strcasecmp(current.GetValue().c_str(),"title")==0){
						titleflag=false;
					}
					else if(strcasecmp(current.GetValue().c_str(),"script")==0){
						scriptflag=false;
					}
				}
				else if (current.GetType()== TEXT){
					if((bodyflag||titleflag)&&!scriptflag)
						ParseText(current.GetValue() + " ",*words);
				}
			}
			return words;
		}

		void HTMLParser::ParseText(string src, LinkedList<string> &list){
			src= StringUtil::TrimCopy(src) + " ";
			StringUtil::ToLower(src);
			//startpos is index of the start of a word, stoppos is index at the end of a word;
			int startpos=0,stoppos=0;
			bool validWord=true;
			while (stoppos<src.length()){
				//looking for start of new word, if not a letter both pointers increment
				if (startpos==stoppos){
					if(isspace(src[startpos])||(!isalnum(src[startpos])
					&& src[startpos]!='_' && src[startpos]!='-' )){
						startpos++;
						stoppos++;
						validWord=true;
					}
					//checks for illegal word (doesn't start with letter)
					else if(!isalpha(src[startpos]) || !validWord){
						validWord=false;
						startpos++;
						stoppos++;
					}
					else
						stoppos++;	//found start of good word
				}
				else{	//searching for end of word
					if(isalnum(src[stoppos])|| src[stoppos]=='_' || src[stoppos]=='-' )
						stoppos++;
					else{
						list.Insert(StringUtil::EncodeToXmlCopy(src.substr(startpos,stoppos-startpos)));
						stoppos++;
						startpos=stoppos;
					}
				}
			}
		}

		LinkedList<string>* HTMLParser::getLinks(const string *html){
			HTMLTokenizer tokenizer(*html);
			LinkedList<string> *links = new LinkedList<string>();
			while(strcasecmp(tokenizer.GetNextToken().GetValue().c_str(),"html")!=0){
				if (!tokenizer.HasNextToken())
					throw new NonHTMLFileException();
			}

			while(tokenizer.HasNextToken()){
				HTMLToken current(tokenizer.GetNextToken());
				if (current.GetType()== TAG_START){
					if(strcasecmp(current.GetValue().c_str(),"a")==0){
						string link= current.GetAttribute("href");
						if (link.length()!=0)
							links->Insert(link);
					}
				}
			}

			return links;
		}






